/*
 * Copyright 2008 Carnegie Mellon University
 * Licensed under the Apache License, Version 2.0 (the "License"); 
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *  
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, 
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied. See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */
package edu.cmu.lti.sepia.servlet;

import java.io.File;
import java.io.IOException;
import java.io.OutputStream;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Calendar;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import edu.cmu.lti.sepia.data.db.SQL;
import edu.cmu.lti.sepia.data.db.UploadedFileDAO;
import edu.cmu.lti.sepia.data.resource.ResourceManager;
import edu.cmu.lti.sepia.infra.system.model.UploadedFile;
import edu.cmu.lti.sepia.util.IOUtil;
import edu.cmu.lti.sepia.util.Logger;

public class FileFetcher extends HttpServlet {

  private static final long serialVersionUID = 1L;

  public void doPost(HttpServletRequest request, HttpServletResponse response)
  throws ServletException, IOException {

    String[] fileIds = request.getParameterValues("fileId");

    String fileId = request.getParameter("fileId");
    
    if (fileIds!=null && fileIds.length>1) {
      doZippedFilePost(request, response, fileIds);
    } else if (fileId!=null) {
      doSingleFilePost(request, response, fileId);
    }
  }
  
  //Simply download files
  public void doSingleFilePost(HttpServletRequest request, HttpServletResponse response, String fileIdString)
  throws ServletException, IOException {
    SQL sql = new SQL();
    try {
      int fileId = Integer.parseInt(fileIdString);
      Logger.log( sql, request.getSession(), "DOWNLOAD FILE", "fileId="+fileId );
      
      UploadedFile uploadedFile = UploadedFileDAO.findById(sql, fileId);
      setContentTypeByFileName(response, uploadedFile.getFileName());
      response.setHeader("Content-Disposition", "attachment; filename=\""+uploadedFile.getFileName()+"\"");
      response.setHeader("progma", "no-cache");
      response.setHeader("Cache-Control", "no-cache");

      File file = new File(ResourceManager.uploadRepository,uploadedFile.getFilePath());
      byte[] bytearray = IOUtil.getByteArrayFromFile(file);
      response.getOutputStream().write(bytearray);
    } catch (Exception e) {
      throw new IOException(e);
    } finally {
      try {
        sql.close();
      } catch (Exception e) {
        e.printStackTrace();
      }
    }
  }
  
  //Simply download files
  public void doZippedFilePost(HttpServletRequest request, HttpServletResponse response, String[] fileIds )
  throws ServletException, IOException {
    SQL sql = new SQL();
    try {
      List<UploadedFile> files = new ArrayList<UploadedFile>(fileIds.length);
      Logger.log( sql, request.getSession(), "DOWNLOAD FILE", "fileIds="+Arrays.toString(fileIds) );
      Set<Integer> history = new HashSet<Integer>(fileIds.length);
      for (int i=0; i<fileIds.length; i++) {
        int fileId = Integer.parseInt(fileIds[i]);
        if (history.contains(fileId)) continue; 
        UploadedFile file = UploadedFileDAO.findById(sql, fileId);
        files.add(file);
        history.add(fileId);
      }
      
      response.setContentType("application/zip");
      response.setHeader("Content-Disposition", "attachment; filename=\"sepia-"+new SimpleDateFormat("yyyyMMdd-HHmm").format(Calendar.getInstance().getTime())+".zip\"");
      response.setHeader("progma", "no-cache");
      response.setHeader("Cache-Control", "no-cache");
      
      toZip(files, response.getOutputStream());
    } catch (Exception e) {
      throw new IOException(e);
    } finally {
      try {
        sql.close();
      } catch (Exception e) {
        e.printStackTrace();
      }
    }
  }
  
  public void toZip( List<UploadedFile> files, OutputStream os ) throws Exception {
    ZipOutputStream zipos = new ZipOutputStream(os);
    
    for ( UploadedFile uploadedFile : files ) {
      ZipEntry entry = new ZipEntry(uploadedFile.getFilePath());
      entry.setMethod(ZipOutputStream.DEFLATED);
      zipos.putNextEntry(entry);
      File file = new File(ResourceManager.uploadRepository,uploadedFile.getFilePath());
      byte[] bytearray = IOUtil.getByteArrayFromFile(file);
      zipos.write(bytearray);
      zipos.closeEntry();
    }
    
    zipos.close();
  }

  private void setContentTypeByFileName( HttpServletResponse response, String fileName ) {
    int pos = fileName.lastIndexOf(".");
    String extension = fileName.substring(pos+1);
    String contentType;
    if (extension.equalsIgnoreCase("zip")) {
      contentType = "application/zip";
    } else if (extension.equalsIgnoreCase("xml")) {
      contentType = "application/xml";
    } else if (extension.equalsIgnoreCase("txt")) {
      contentType = "text/plain";
    } else if (extension.equalsIgnoreCase("xls")) {
      contentType = "application/vnd.ms-excel";
    } else if (extension.equalsIgnoreCase("ppt")) {
      contentType = "application/vnd.ms-powerpoint";
    } else if (extension.equalsIgnoreCase("doc")) {
      contentType = "application/msword";
    } else if (extension.equalsIgnoreCase("pdf")) {
      contentType = "application/pdf";
    } else {
      contentType = "application/octetstream";
    }
    
    response.setContentType(contentType);
  }
   
}
